package com.io;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

/**
 * 数独游戏类，继承自JFrame，实现数独游戏界面及逻辑。
 */
public class SudokuGame extends JFrame {

    // 用于显示数独的九宫格按钮数组
    private JButton[][] buttons = new JButton[9][9];
    // 用于存储数独状态的SudokuBoard对象
    private SudokuBoard sudokuBoard;

    /**
     * 构造函数，初始化数独游戏窗口及组件。
     */
    public SudokuGame() {
        setTitle("数独游戏"); // 设置窗口标题
        setSize(400, 400); // 设置窗口大小
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 设置关闭操作

        sudokuBoard = new SudokuBoard(); // 创建SudokuBoard对象
        initializeBoard(); // 初始化数独棋盘
    }

    /**
     * 初始化数独棋盘，包括创建按钮、设置布局、添加事件监听器等。
     */
    private void initializeBoard() {
        // 使用GridLayout创建3x3的网格布局
        setLayout(new GridLayout(9, 9));

        // 遍历所有单元格，创建按钮并添加到面板上
        for (int i = 0; i < 9; i++) {
            for (int j = 0; j < 9; j++) {
                buttons[i][j] = new JButton();
                buttons[i][j].setFont(new Font("Arial", Font.BOLD, 24)); // 设置字体样式和大小
                buttons[i][j].addActionListener(new ButtonListener()); // 添加按钮监听器
                add(buttons[i][j]); // 将按钮添加到窗口
            }
        }

        // 设置数独初始状态（此处仅为示例，需替换为实际数独谜题）
        sudokuBoard.setCell(0, 0, 5);
        sudokuBoard.setCell(1, 3, 3);
        sudokuBoard.setCell(2, 6, 7);
        updateBoard(); // 更新棋盘显示
    }

    /**
     * 根据当前SudokuBoard的状态更新GUI上按钮的显示。
     */
    private void updateBoard() {
        // 遍历所有单元格，根据SudokuBoard中的值设置对应按钮的文本
        for (int i = 0; i < 9; i++) {
            for (int j = 0; j < 9; j++) {
                int value = sudokuBoard.getCell(i, j);
                buttons[i][j].setText(value == 0 ? "" : String.valueOf(value));
            }
        }
    }

    /**
     * 内部类，实现按钮点击事件监听器。
     */
    private class ButtonListener implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent e) {
            // 获取触发事件的按钮
            JButton button = (JButton) e.getSource();

            // 确定按钮在数独棋盘中的位置（行、列）
            int row = -1;
            int col = -1;
            for (int i = 0; i < 9; i++) {
                for (int j = 0; j < 9; j++) {
                    if (buttons[i][j] == button) {
                        row = i;
                        col = j;
                        break;
                    }
                }
            }

            // 处理按钮点击逻辑：清除已有数字或尝试填入数字
            if (sudokuBoard.getCell(row, col) != 0) {
                sudokuBoard.setCell(row, col, 0);
            } else {
                // 尝试填入数字1到9，找到第一个满足数独规则的数字
                for (int num = 1; num <= 9; num++) {
                    if (sudokuBoard.isSafe(row, col, num)) {
                        sudokuBoard.setCell(row, col, num);
                        break;
                    }
                }
            }

            // 更新棋盘显示
            updateBoard();
        }
    }

    /**
     * 主方法，启动数独游戏。
     *
     * @param args 命令行参数
     */
    public static void main(String[] args) {
        // 使用SwingUtilities.invokeLater确保在事件调度线程中创建并显示窗口
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new SudokuGame().setVisible(true);
            }
        });
    }
}

/**
 * SudokuBoard类，用于存储数独状态以及实现数独规则相关的方法。
 */
class SudokuBoard {
    // 存储数独状态的二维数组
    private int[][] board = new int[9][9];

    /**
     * 获取指定位置的数字。
     *
     * @param row 行索引
     * @param col 列索引
     * @return 该位置的数字
     */
    public int getCell(int row, int col) {
        return board[row][col];
    }

    /**
     * 设置指定位置的数字。
     *
     * @param row 行索引
     * @param col 列索引
     * @param value 要设置的数字
     */
    public void setCell(int row, int col, int value) {
        board[row][col] = value;
    }

    /**
     * 检查指定位置填入数字num是否符合数独规则。
     *
     * @param row 行索引
     * @param col 列索引
     * @param num 待检查的数字
     * @return 若填入num符合规则，返回true；否则返回false
     */
    public boolean isSafe(int row, int col, int num) {
        // 示例实现，仅检查行、列和3x3宫格内是否有重复的数字
        // 实际应用中需要根据完整的数独规则进行完善
        for (int i = 0; i < 9; i++) {
            if (board[row][i] == num || board[i][col] == num) {
                return false;
            }
        }

        // 计算3x3宫格的起始行、列索引
        int startRow = row - row % 3;
        int startCol = col - col % 3;

        // 遍历该3x3宫格内的所有单元格，检查是否有重复的num
        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 3; j++) {
                if (board[startRow + i][startCol + j] == num) {
                    return false;
                }
            }
        }

        return true;
    }
}
